import Bull, { Queue, Job } from 'bull';
import { QUEUE_NAMES, REDIS_KEYS } from '@weubi/shared';

export class QueueService {
  private crawlerQueue: Queue;
  private emailQueue: Queue;
  private notificationQueue: Queue;

  constructor() {
    const redisConfig = {
      host: process.env.REDIS_HOST || 'localhost',
      port: parseInt(process.env.REDIS_PORT || '6379'),
      password: process.env.REDIS_PASSWORD || undefined,
    };

    // 创建队列
    this.crawlerQueue = new Bull(QUEUE_NAMES.CRAWLER, {
      redis: redisConfig,
      defaultJobOptions: {
        removeOnComplete: 100, // 保留最近100个完成的任务
        removeOnFail: 50,      // 保留最近50个失败的任务
        attempts: 3,           // 重试3次
        backoff: {
          type: 'exponential',
          delay: 2000,
        },
      },
    });

    this.emailQueue = new Bull(QUEUE_NAMES.EMAIL, {
      redis: redisConfig,
      defaultJobOptions: {
        removeOnComplete: 50,
        removeOnFail: 25,
        attempts: 5,
        backoff: {
          type: 'exponential',
          delay: 1000,
        },
      },
    });

    this.notificationQueue = new Bull(QUEUE_NAMES.NOTIFICATION, {
      redis: redisConfig,
      defaultJobOptions: {
        removeOnComplete: 200,
        removeOnFail: 50,
        attempts: 2,
        backoff: {
          type: 'fixed',
          delay: 5000,
        },
      },
    });

    this.setupEventHandlers();
  }

  // 添加爬虫任务
  async addCrawlerJob(data: {
    taskId: string;
    url: string;
    engine: string;
    config: any;
  }, options?: any): Promise<Job> {
    return await this.crawlerQueue.add('crawl', data, {
      priority: this.getPriority(data.config?.priority),
      delay: data.config?.delay || 0,
      ...options,
    });
  }

  // 添加邮件任务
  async addEmailJob(data: {
    to: string;
    subject: string;
    template: string;
    data: any;
  }): Promise<Job> {
    return await this.emailQueue.add('send', data);
  }

  // 添加通知任务
  async addNotificationJob(data: {
    userId: string;
    type: string;
    title: string;
    message: string;
    data?: any;
  }): Promise<Job> {
    return await this.notificationQueue.add('notify', data);
  }

  // 获取队列状态
  async getQueueStats() {
    const crawlerStats = await this.getQueueMetrics(this.crawlerQueue);
    const emailStats = await this.getQueueMetrics(this.emailQueue);
    const notificationStats = await this.getQueueMetrics(this.notificationQueue);

    return {
      crawler: crawlerStats,
      email: emailStats,
      notification: notificationStats,
    };
  }

  // 暂停队列
  async pauseQueue(queueName: string): Promise<void> {
    const queue = this.getQueueByName(queueName);
    if (queue) {
      await queue.pause();
    }
  }

  // 恢复队列
  async resumeQueue(queueName: string): Promise<void> {
    const queue = this.getQueueByName(queueName);
    if (queue) {
      await queue.resume();
    }
  }

  // 清空队列
  async cleanQueue(queueName: string, type: 'completed' | 'failed' | 'active' | 'wait' = 'completed'): Promise<void> {
    const queue = this.getQueueByName(queueName);
    if (queue) {
      await queue.clean(0, type);
    }
  }

  // 获取任务详情
  async getJob(queueName: string, jobId: string): Promise<Job | null> {
    const queue = this.getQueueByName(queueName);
    if (queue) {
      return await queue.getJob(jobId);
    }
    return null;
  }

  // 重试失败的任务
  async retryFailedJobs(queueName: string): Promise<void> {
    const queue = this.getQueueByName(queueName);
    if (queue) {
      const failedJobs = await queue.getFailed();
      for (const job of failedJobs) {
        await job.retry();
      }
    }
  }

  // 设置事件处理器
  private setupEventHandlers(): void {
    // 爬虫队列事件
    this.crawlerQueue.on('completed', (job: Job, result: any) => {
      console.log(`Crawler job ${job.id} completed:`, result);
    });

    this.crawlerQueue.on('failed', (job: Job, err: Error) => {
      console.error(`Crawler job ${job.id} failed:`, err.message);
    });

    this.crawlerQueue.on('stalled', (job: Job) => {
      console.warn(`Crawler job ${job.id} stalled`);
    });

    // 邮件队列事件
    this.emailQueue.on('completed', (job: Job) => {
      console.log(`Email job ${job.id} completed`);
    });

    this.emailQueue.on('failed', (job: Job, err: Error) => {
      console.error(`Email job ${job.id} failed:`, err.message);
    });

    // 通知队列事件
    this.notificationQueue.on('completed', (job: Job) => {
      console.log(`Notification job ${job.id} completed`);
    });

    this.notificationQueue.on('failed', (job: Job, err: Error) => {
      console.error(`Notification job ${job.id} failed:`, err.message);
    });
  }

  // 获取队列指标
  private async getQueueMetrics(queue: Queue) {
    const waiting = await queue.getWaiting();
    const active = await queue.getActive();
    const completed = await queue.getCompleted();
    const failed = await queue.getFailed();
    const delayed = await queue.getDelayed();

    return {
      name: queue.name,
      waiting: waiting.length,
      active: active.length,
      completed: completed.length,
      failed: failed.length,
      delayed: delayed.length,
      isPaused: await queue.isPaused(),
    };
  }

  // 根据名称获取队列
  private getQueueByName(name: string): Queue | null {
    switch (name) {
      case QUEUE_NAMES.CRAWLER:
        return this.crawlerQueue;
      case QUEUE_NAMES.EMAIL:
        return this.emailQueue;
      case QUEUE_NAMES.NOTIFICATION:
        return this.notificationQueue;
      default:
        return null;
    }
  }

  // 获取优先级数值
  private getPriority(priority?: string): number {
    switch (priority) {
      case 'urgent':
        return 1;
      case 'high':
        return 2;
      case 'normal':
        return 3;
      case 'low':
        return 4;
      default:
        return 3;
    }
  }
}

// 设置队列处理器
export async function setupQueues(): Promise<void> {
  console.log('Setting up queue processors...');
  
  // 这里会在爬虫服务中实现具体的处理器
  // 暂时只是初始化队列服务
  
  console.log('Queue processors setup completed');
}
